﻿using System;
using System.Collections.Generic;
using System.Linq;
using Citi.Import.Util;
using Citi.ResourceConsolidation.Domain.Utils;

namespace Citi.ResourceConsolidation.Domain
{
    public partial class Resource
    {
        private const string GeIdColumnName = "GEID";
        private const string SoeIdColumnName = "SOEID";
        private const string FirstNameColumnName = "FirstName";
        private const string LastNameColumnName = "LastName";
        private const string FullNameColumnName = "Full Name";
        private const string EmployeeStatusColumn = "Empl Status";

        public static readonly List<Definition<Resource>> GDWDefinition = new List<Definition<Resource>>
            {
                new Definition<Resource> { ModelProperty = x => x.GeId, MaxLength = 15, Required = true, ColumnName = GeIdColumnName, CustomConversionMethod = ValidateGeId},
                new Definition<Resource> { ModelProperty = x => x.SoeId, MaxLength = 7, Required = true, ColumnName = SoeIdColumnName},
                new Definition<Resource> { ModelProperty = x => x.FullName, MaxLength = 120, Required = true, ColumnName = FullNameColumnName},
                new Definition<Resource> { ModelProperty = x => x.Active, MaxLength = 50, Required = true, ColumnName = EmployeeStatusColumn, CustomConversionMethod = ValidateStatus},
            };

        public static readonly List<Definition<Resource>> MatrixDefinition = new List<Definition<Resource>>
            {
                new Definition<Resource> { ModelProperty = x => x.GeId, MaxLength = 15, Required = true, ColumnName = GeIdColumnName, CustomConversionMethod = ValidateGeId},
                new Definition<Resource> { ModelProperty = x => x.SoeId, MaxLength = 7, Required = true, ColumnName = SoeIdColumnName},
                new Definition<Resource> { ModelProperty = x => x.FullName, MaxLength = 120, Required = true, ColumnName = FullNameColumnName},                
            };

        public static readonly List<Definition<Resource>> NEMSDefinition = new List<Definition<Resource>>
            {
                new Definition<Resource> { ModelProperty = x => x.GeId, MaxLength = 15, Required = true, ColumnName = "GEID -", CustomConversionMethod = ValidateGeId},
                new Definition<Resource> { ModelProperty = x => x.SoeId, MaxLength = 7, Required = true, ColumnName = SoeIdColumnName},
                new Definition<Resource> { ModelProperty = x => x.FullName, MaxLength = 120, Required = true, ColumnName = FirstNameColumnName, CustomConversionMethod = ValidateNEMSFullname},                
                new Definition<Resource> { ModelProperty = x => x.Active, MaxLength = 50, Required = true, ColumnName = "Acc Status", CustomConversionMethod = ValidateStatus},
                
            };

        private static object ValidateStatus(ref Resource model, string value, List<string> fields, ref string error, List<string> headers = null)
        {
            if (String.IsNullOrEmpty(value))
            {
                error = String.Format("The field {0} can not be null", EmployeeStatusColumn);
                return Conversion.Validation.Failed;
            }

            return value.Substring(0,1);
        }

        private static object ValidateNEMSFullname(ref Resource model, string value, List<string> fields, ref string error, List<string> headers = null)
        {
            if (String.IsNullOrEmpty(value))
            {
                error = String.Format("The field {0} can not be null", FirstNameColumnName);
                return Conversion.Validation.Failed;
            }

            //return string.Format("{0}, {1}", fields[headers.IndexOf("LASTNAME")], value);
            return string.Format("{0}, {1}", fields[6].ToString(), value);
        }


        private static object ValidateGeId(ref Resource model, string value, List<string> fields, ref string error, List<string> headers = null)
        {
            if (String.IsNullOrEmpty(value))
            {
                error = "The field GEID can not be null";
                return Conversion.Validation.Failed;
            }

            var domain = CacheFacade.Get(new Resource().SelectAll<Resource>).FirstOrDefault(x => x.GeId == value);

            if (domain != null)
            {
                model = domain;
                return Conversion.Validation.Validated;
            }

            return value;
        }

        public Resource GetByGeid(string geid)
        {
            return SelectAll<Resource>().FirstOrDefault(x => x.GeId == geid);
        }

        public List<string> GetActiveGeid()
        {
            return SelectAll<Resource>().Where(x => x.Active == "A").Select(x => x.GeId) .ToList();
        }

        public static void Save(IEnumerable<Resource> resources, string type)
        {
            var resourcesToSave = resources.Distinct(new ResourceComparer()).Where(x => x != null && !String.IsNullOrEmpty(x.GeId) && x.Id == 0).ToList();

            if (!resourcesToSave.Any()) return;
            resourcesToSave.First().Save(resourcesToSave, 100);

            CacheFacade.Clear(typeof(Resource));
            Context.ClearContext();
        }
    }

    public class ResourceComparer : IEqualityComparer<Resource>
    {
        public bool Equals(Resource x, Resource y)
        {
            if (ReferenceEquals(x, y)) return true;
            if (ReferenceEquals(x, null) || ReferenceEquals(y, null))
                return false;

            return x.GeId == y.GeId && x.Id == y.Id && x.SoeId == y.SoeId && x.FullName == y.FullName 
                        && x.Active == y.Active && x.Functional == y.Functional;
        }

        public int GetHashCode(Resource item)
        {
            if (ReferenceEquals(item, null)) return 0;

            int hashDescription = item.GeId == null ? 0 : item.GeId.GetHashCode();
            int hashId = item.GeId == null ? 0 : item.Id.GetHashCode();
            int hashCode = item.SoeId == null ? 0 : item.SoeId.GetHashCode();

            return hashDescription ^ hashId ^ hashCode;
        }
    }
}
